#include "pipe.hh"
#include <utility>
#include <vector>
#include <memory>
#include <iostream>

std::vector<Position> 
VerticalPipe::nextPositions() const
{
    std::vector<Position> nextPositions{};
    nextPositions.emplace_back(this->_position.first - 1, this->_position.second);
    nextPositions.emplace_back(this->_position.first + 1, this->_position.second);
    return nextPositions;
}

std::vector<Position> 
HorizontalPipe::nextPositions() const
{
    std::vector<Position> nextPositions{};
    nextPositions.emplace_back(this->_position.first, this->_position.second - 1);
    nextPositions.emplace_back(this->_position.first, this->_position.second + 1);
    return nextPositions;
}

std::vector<Position> 
NorthEastPipe::nextPositions() const
{
    std::vector<Position> nextPositions{};
    nextPositions.emplace_back(this->_position.first - 1, this->_position.second);
    nextPositions.emplace_back(this->_position.first, this->_position.second + 1);
    return nextPositions;
}

std::vector<Position> 
NorthWestPipe::nextPositions() const
{
    std::vector<Position> nextPositions{};
    nextPositions.emplace_back(this->_position.first - 1, this->_position.second);
    nextPositions.emplace_back(this->_position.first, this->_position.second - 1);
    return nextPositions;
}

std::vector<Position> 
SouthEastPipe::nextPositions() const
{
    std::vector<Position> nextPositions{};
    nextPositions.emplace_back(this->_position.first + 1, this->_position.second);
    nextPositions.emplace_back(this->_position.first, this->_position.second + 1);
    return nextPositions;
}

std::vector<Position>
SouthWestPipe::nextPositions() const
{
    std::vector<Position> nextPositions{};
    nextPositions.emplace_back(this->_position.first + 1, this->_position.second);
    nextPositions.emplace_back(this->_position.first, this->_position.second - 1);
    return nextPositions;
}

std::vector<Position> 
GroundPipe::nextPositions() const
{
    return {};
}

std::shared_ptr<Pipe> 
PipeFactory::create(char token, const Position& pos)
{
    switch (token)
    {
        case '|': return std::make_shared<VerticalPipe>(pos);
        case '-': return std::make_shared<HorizontalPipe>(pos);
        case 'L': return std::make_shared<NorthEastPipe>(pos);
        case 'J': return std::make_shared<NorthWestPipe>(pos);
        case 'F': return std::make_shared<SouthEastPipe>(pos);
        case '7': return std::make_shared<SouthWestPipe>(pos);
        case '.': return std::make_shared<GroundPipe>(pos);
        default:
        {
            std::cout << '\'' << token << '\'' << " is not a valid token!" << std::endl;
            std::exit(1);
        }
    }
    return nullptr;
}